/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.uml_generator.transformer;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

import com.genia.toolbox.uml_generator.bean.ModelGeneratorContext;
import com.genia.toolbox.uml_generator.manager.ModelDecorator;
import com.genia.toolbox.uml_generator.model.DataTypeModel;
import com.genia.toolbox.uml_generator.model.impl.DataTypeModelImpl;
import com.genia.toolbox.uml_generator.model.impl.ExistentDataTypeModel;

/**
 * this class handle the input of nodes from xmi to model.
 */
public class DataTypeInputHandler
    extends AbstractInputHandler<Object>
{

  /**
   * the {@link ModelDecorator} to use.
   */
  private ModelDecorator modelDecorator;

  /**
   * the {@link Pattern} for a {@link List}.
   */
  private static final Pattern LIST_REGEXP = Pattern.compile("List<(.*)>");

  /**
   * the {@link Pattern} for a {@link Set}.
   */
  private static final Pattern SET_REGEXP = Pattern.compile("Set<(.*)>");

  /**
   * the {@link Pattern} for a {@link Map}.
   */
  private static final Pattern MAP_REGEXP = Pattern.compile("Map<(.*),(.*)>");



  /**
   * the actual method that parse the current {@link Element}.
   * 
   * @param context
   *          the generation context
   * @param firstPass
   *          wether it is the first or second pass
   * @param element
   *          the element to parse
   * @param parent
   *          the generated parent model
   */
  public void processContent(final ModelGeneratorContext context, final boolean firstPass, final Element element, final Object parent)
  {
    if (firstPass) {
      final DataTypeModel dataTypeModel = new DataTypeModelImpl();
      fillCommonValue(context, element, dataTypeModel);
      context.addDataTypeModel(getSpecialDataTypeModel(context, dataTypeModel));
    }
  }



  /**
   * returns the {@link DataTypeModel} associated to the given qualified name.
   * 
   * @param qualifiedName
   *          the qualified name to retrieve a {@link DataTypeModel} for
   * @return the {@link DataTypeModel} associated to the given qualified name
   */
  private DataTypeModel getDataTypeModel(String qualifiedName)
  {
    final DataTypeModel dataTypeModel = new DataTypeModelImpl();
    int lastDotIndex = qualifiedName.lastIndexOf('.');
    dataTypeModel.setPackageName(qualifiedName.substring(0, lastDotIndex));
    dataTypeModel.setName(qualifiedName.substring(lastDotIndex + 1));
    return dataTypeModel;
  }



  /**
   * returns a {@link DataTypeModel} to handle collection types.
   * 
   * @param context
   *          the generation context
   * @param dataTypeModel
   *          the original {@link DataTypeModel}
   * @return a {@link DataTypeModel} to handle collection types
   */
  private DataTypeModel getSpecialDataTypeModel(final ModelGeneratorContext context, DataTypeModel dataTypeModel)
  {
    try {
      Matcher matcher = null;
      matcher = LIST_REGEXP.matcher(dataTypeModel.getName());
      if (matcher.matches()) {
        return getModelDecorator().getGenericObject(new ExistentDataTypeModel(dataTypeModel.getUmlId(), List.class, "Array"), getDataTypeModel(StringUtils.trimWhitespace(matcher.group(1))));
      }
      matcher = SET_REGEXP.matcher(dataTypeModel.getName());
      if (matcher.matches()) {
        return getModelDecorator().getGenericObject(new ExistentDataTypeModel(dataTypeModel.getUmlId(), Set.class, "Hash"), getDataTypeModel(StringUtils.trimWhitespace(matcher.group(1))));
      }
      matcher = MAP_REGEXP.matcher(dataTypeModel.getName());
      if (matcher.matches()) {
        return getModelDecorator().getGenericObject(new ExistentDataTypeModel(dataTypeModel.getUmlId(), Map.class, "Hash"), getDataTypeModel(StringUtils.trimWhitespace(matcher.group(1))),
            getDataTypeModel(StringUtils.trimWhitespace(matcher.group(2))));
      }
    }
    catch (Exception e) {
      context.getErrors().add(e.getMessage());
    }
    return dataTypeModel;
  }



  /**
   * getter for the modelDecorator property.
   * 
   * @return the modelDecorator
   */
  public ModelDecorator getModelDecorator()
  {
    return modelDecorator;
  }



  /**
   * setter for the modelDecorator property.
   * 
   * @param modelDecorator
   *          the modelDecorator to set
   */
  public void setModelDecorator(ModelDecorator modelDecorator)
  {
    this.modelDecorator = modelDecorator;
  }
}
